package com.xyht.sca_s.student_manage_system.modules.leave.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xyht.sca_s.student_manage_system.common.commonReturn.CommonCodeEnum;
import com.xyht.sca_s.student_manage_system.common.commonReturn.CommonResult;
import com.xyht.sca_s.student_manage_system.common.commonReturn.ExceptionCast;
import com.xyht.sca_s.student_manage_system.common.commonReturn.ResponseResult;
import com.xyht.sca_s.student_manage_system.common.util.CacheUtil;
import com.xyht.sca_s.student_manage_system.common.util.TimeUtil;
import com.xyht.sca_s.student_manage_system.modules.leave.entity.SmsLeave;
import com.xyht.sca_s.student_manage_system.modules.leave.entity.SmsLeaveDetail;
import com.xyht.sca_s.student_manage_system.modules.leave.entity.SmsLeaveProcess;
import com.xyht.sca_s.student_manage_system.modules.leave.entity.SmsLeaveProcessLevel;
import com.xyht.sca_s.student_manage_system.modules.leave.entity.req.SmsLeaveAddReq;
import com.xyht.sca_s.student_manage_system.modules.leave.entity.req.SmsLeaveAllowReq;
import com.xyht.sca_s.student_manage_system.modules.leave.entity.req.SmsLeaveConfirmResp;
import com.xyht.sca_s.student_manage_system.modules.leave.entity.resp.LeaveDetailResp;
import com.xyht.sca_s.student_manage_system.modules.leave.entity.resp.SmsLeaveDetailResp;
import com.xyht.sca_s.student_manage_system.modules.leave.entity.resp.SmsLeaveResp;
import com.xyht.sca_s.student_manage_system.modules.leave.entity.resp.SmsLeaveUserResp;
import com.xyht.sca_s.student_manage_system.modules.leave.mapper.SmsLeaveDetailMapper;
import com.xyht.sca_s.student_manage_system.modules.leave.mapper.SmsLeaveMapper;
import com.xyht.sca_s.student_manage_system.modules.leave.mapper.SmsLeaveProcessLevelMapper;
import com.xyht.sca_s.student_manage_system.modules.leave.mapper.SmsLeaveProcessMapper;
import com.xyht.sca_s.student_manage_system.modules.leave.service.SmsLeaveService;
import com.xyht.sca_s.student_manage_system.modules.newTips.myEnum.AppTypeEnum;
import com.xyht.sca_s.student_manage_system.modules.newTips.myEnum.RangeTypeEnum;
import com.xyht.sca_s.student_manage_system.modules.newTips.myEnum.TipsTypeEnum;
import com.xyht.sca_s.student_manage_system.modules.newTips.util.NewTipsUtil;
import com.xyht.sca_s.student_manage_system.modules.org.entity.SmsOrgStructure;
import com.xyht.sca_s.student_manage_system.modules.org.entity.SmsOrgUserRelation;
import com.xyht.sca_s.student_manage_system.modules.org.mapper.SmsOrgStructureMapper;
import com.xyht.sca_s.student_manage_system.modules.org.mapper.SmsOrgUserRelationMapper;
import com.xyht.sca_s.student_manage_system.modules.org.util.CommonUtil;
import com.xyht.sca_s.student_manage_system.modules.qr.entity.SmsQr;
import com.xyht.sca_s.student_manage_system.modules.qr.mapper.SmsQrMapper;
import com.xyht.sca_s.student_manage_system.modules.student.entity.SmsStudentInfo;
import com.xyht.sca_s.student_manage_system.modules.student.entity.SmsUserStudentRelation;
import com.xyht.sca_s.student_manage_system.modules.student.mapper.SmsStudentInfoMapper;
import com.xyht.sca_s.student_manage_system.modules.student.mapper.SmsUserStudentRelationMapper;
import com.xyht.sca_s.student_manage_system.modules.teacher.mapper.SmsTeacherInfoMapper;
import com.xyht.sca_s.student_manage_system.modules.user.entity.SmsUser;
import com.xyht.sca_s.student_manage_system.modules.user.entity.SmsUserRoleRelation;
import com.xyht.sca_s.student_manage_system.modules.user.mapper.SmsRoleMapper;
import com.xyht.sca_s.student_manage_system.modules.user.mapper.SmsUserMapper;
import com.xyht.sca_s.student_manage_system.modules.user.mapper.SmsUserRoleRelationMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import static com.xyht.sca_s.student_manage_system.common.util.ParamCheckUtil.isNullOrEmpty;
import static com.xyht.sca_s.student_manage_system.modules.leave.constant.LeaveAllowFlag.*;
import static com.xyht.sca_s.student_manage_system.modules.leave.constant.LeaveConfirmFlag.*;
import static com.xyht.sca_s.student_manage_system.modules.org.constants.OrgTypeConstant.ORG_TYPE_CLASS;
import static com.xyht.sca_s.student_manage_system.modules.qr.constant.QrTypeConstant.QR_TYPE_LEAVE;
import static com.xyht.sca_s.student_manage_system.modules.user.constant.RoleIDConstant.ROLE_INSTRUCTOR_ID;
import static com.xyht.sca_s.student_manage_system.modules.user.constant.RoleIDConstant.ROLE_STUDENT_ID;

/**
 * <p>
 * 请假管理 服务实现类
 * </p>
 *
 * @author XYHT
 * @since 2022-12-06
 */
@Service
public class SmsLeaveServiceImpl extends ServiceImpl<SmsLeaveMapper, SmsLeave> implements SmsLeaveService {
    @Autowired
    private SmsUserRoleRelationMapper smsUserRoleRelationMapper;
    @Autowired
    private SmsUserStudentRelationMapper smsUserStudentRelationMapper;
    @Autowired
    private SmsStudentInfoMapper smsStudentInfoMapper;
    @Autowired
    private SmsOrgUserRelationMapper smsOrgUserRelationMapper;
    @Autowired
    private SmsOrgStructureMapper smsOrgStructureMapper;
    @Autowired
    private SmsLeaveMapper smsLeaveMapper;
    @Autowired
    private SmsLeaveProcessMapper smsLeaveProcessMapper;
    @Autowired
    private SmsLeaveProcessLevelMapper smsLeaveProcessLevelMapper;
    @Autowired
    private SmsLeaveDetailMapper smsLeaveDetailMapper;
    @Autowired
    private SmsTeacherInfoMapper smsTeacherInfoMapper;
    @Autowired
    private SmsUserMapper smsUserMapper;
    @Autowired
    private SmsRoleMapper smsRoleMapper;
    @Autowired
    private CacheUtil cacheUtil;
    @Autowired
    private SmsQrMapper smsQrMapper;
    @Autowired
    private NewTipsUtil newTipsUtil;
    @Autowired
    private CommonUtil commonUtil;

    @Override
    @Transactional
    public ResponseResult addLeave(SmsLeaveAddReq smsLeaveAddReq, String user_id) {
        if (isNullOrEmpty(smsLeaveAddReq.getTotalTime()) || isNullOrEmpty(smsLeaveAddReq.getLeaveTime())
                || isNullOrEmpty(smsLeaveAddReq.getComeTime()) || isNullOrEmpty(smsLeaveAddReq.getLeaveType())
                || isNullOrEmpty(smsLeaveAddReq.getOutContact()) || isNullOrEmpty(smsLeaveAddReq.getOutContactTel())
                || isNullOrEmpty(smsLeaveAddReq.getOutContactRelation()) || isNullOrEmpty(smsLeaveAddReq.getOutPlace())
                || isNullOrEmpty(smsLeaveAddReq.getLeaveReason())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        SmsLeave smsLeave;

        //用户角色校验
        QueryWrapper<SmsUserRoleRelation> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(SmsUserRoleRelation::getUserId, user_id)
                .eq(SmsUserRoleRelation::getRoleId, ROLE_STUDENT_ID);
        SmsUserRoleRelation adminRole = smsUserRoleRelationMapper.selectOne(queryWrapper);
        if (adminRole == null) {
            return CommonResult.failed(CommonCodeEnum.APPLY_ROLE_NOT_EXIST);
        }

        //用户信息校验
        QueryWrapper<SmsUserStudentRelation> userStudentRelationQueryWrapper = new QueryWrapper<>();
        userStudentRelationQueryWrapper.lambda().eq(SmsUserStudentRelation::getUserId, user_id);
        SmsUserStudentRelation userStudentRelation = smsUserStudentRelationMapper.selectOne(userStudentRelationQueryWrapper);
        if (userStudentRelation == null) {
            return CommonResult.failed(CommonCodeEnum.USER_NOT_STUDENT_INFO);
        }
        SmsStudentInfo smsStudentInfo = smsStudentInfoMapper.selectById(userStudentRelation.getStuId());
        if (smsStudentInfo == null) {
            return CommonResult.failed(CommonCodeEnum.USER_NOT_STUDENT_INFO);
        }

        //用户组织班级校验
        QueryWrapper<SmsOrgUserRelation> orgUserRelationQueryWrapper = new QueryWrapper<>();
        orgUserRelationQueryWrapper.lambda().eq(SmsOrgUserRelation::getUserId, user_id);
        List<SmsOrgUserRelation> orgUserRelationList = smsOrgUserRelationMapper.selectList(orgUserRelationQueryWrapper);
        if (orgUserRelationList == null || orgUserRelationList.size() < 1) {
            return CommonResult.failed(CommonCodeEnum.USER_NOT_ORG_INFO);
        }
        List<String> orgIDList = orgUserRelationList.stream().map(SmsOrgUserRelation::getOrgId).collect(Collectors.toList());
        QueryWrapper<SmsOrgStructure> orgStructureQueryWrapper = new QueryWrapper<>();
        orgStructureQueryWrapper.lambda().in(SmsOrgStructure::getId, orgIDList).eq(SmsOrgStructure::getLevel, ORG_TYPE_CLASS);
        List<SmsOrgStructure> orgStructureList = smsOrgStructureMapper.selectList(orgStructureQueryWrapper);
        if (orgStructureList == null || orgStructureList.size() < 1) {
            return CommonResult.failed(CommonCodeEnum.USER_NOT_CLASS_INFO);
        }
        Integer stuClassOrgId = orgStructureList.get(0).getId();

        //用户是否有在申请中
        QueryWrapper<SmsLeave> leaveQueryWrapper = new QueryWrapper<>();
        leaveQueryWrapper.lambda().eq(SmsLeave::getUserId, user_id)
                .eq(SmsLeave::getIsAllow, ALLOW_FLAG_WAIT);
        List<SmsLeave> stuLeavesAllowList = smsLeaveMapper.selectList(leaveQueryWrapper);
        if (stuLeavesAllowList != null && stuLeavesAllowList.size() > 0) {
            return CommonResult.failed(CommonCodeEnum.LEAVE_APPLY_EXIST);
        }

        //查询本人是否销假之前审批
//        QueryWrapper<StuLeaves> wrapper = new QueryWrapper<>();
//        wrapper.lambda().eq(StuLeaves::getAdminId, admin_id)
//                .eq(StuLeaves::getLeaveConfirm, LEAVE_NOT_CONFIRM).ne(StuLeaves::getIsAllow, ALLOW_CANCEL);
//        List<StuLeaves> stuLeavesList = stuLeavesMapper.selectList(wrapper);
//        if (stuLeavesList != null && stuLeavesList.size() > 0) {
//            return CommonResult.failed("有未销假记录，请完成销假后继续申请");
//        }
        SmsUser smsUser = cacheUtil.getUserInfo(user_id);

        smsLeave = new SmsLeave();
        BeanUtils.copyProperties(smsLeaveAddReq, smsLeave);
        //检查相应请假流程
        QueryWrapper<SmsLeaveProcess> leaveProcessQueryWrapper = new QueryWrapper<>();
        leaveProcessQueryWrapper.lambda().lt(SmsLeaveProcess::getStartHour, smsLeaveAddReq.getTotalTime())
                .ge(SmsLeaveProcess::getEndHour, smsLeaveAddReq.getTotalTime());
        List<SmsLeaveProcess> leaveProcessList = smsLeaveProcessMapper.selectList(leaveProcessQueryWrapper);
        if (leaveProcessList != null && leaveProcessList.size() == 1) {
            smsLeave.setProcessId(leaveProcessList.get(0).getId());
        } else {
            return CommonResult.failed(CommonCodeEnum.PROCESS_ERR);
        }

        //保存
        smsLeave.setStuName(smsStudentInfo.getStuName());
        smsLeave.setStuNo(smsStudentInfo.getStuNo());
        smsLeave.setUserId(user_id);
        smsLeave.setStuPic(smsUser.getUserPic());
        smsLeave.setStuId(userStudentRelation.getStuId());
        smsLeave.setStuClass(stuClassOrgId.toString());
        smsLeaveMapper.insert(smsLeave);
        if (isNullOrEmpty(smsLeave.getId())) {
            ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.FAIL));
        }

        boolean is_first = true;
        String role_name = "";
        String role_id = "";
        String process_detail_id = "";

        //保存审批流程
        QueryWrapper<SmsLeaveProcessLevel> leaveProcessLevelQueryWrapper = new QueryWrapper<>();
        leaveProcessLevelQueryWrapper.lambda().eq(SmsLeaveProcessLevel::getProcessId, smsLeave.getProcessId())
                .orderByAsc(SmsLeaveProcessLevel::getSort);
        List<SmsLeaveProcessLevel> leaveProcessLevelList = smsLeaveProcessLevelMapper.selectList(leaveProcessLevelQueryWrapper);
        if (leaveProcessLevelList != null && leaveProcessLevelList.size() > 0) {
            for (SmsLeaveProcessLevel processLevel : leaveProcessLevelList) {
                //获取角色名
                String roleName = smsRoleMapper.selectById(processLevel.getRoleId()).getRoleName();

                SmsLeaveDetail smsLeaveDetail = new SmsLeaveDetail();
                smsLeaveDetail.setAllowSort(processLevel.getSort());
                smsLeaveDetail.setLeaveId(smsLeave.getId());
                smsLeaveDetail.setRoleId(processLevel.getRoleId());
                smsLeaveDetail.setRoleName(roleName);
                smsLeaveDetailMapper.insert(smsLeaveDetail);

                if (is_first) {
                    is_first = false;
                    role_name = roleName;
                    role_id = processLevel.getRoleId();
                    process_detail_id = smsLeaveDetail.getId();
                }

            }
        }

        //发布消息通知待办
        RangeTypeEnum range_type = RangeTypeEnum.RANGE_TYPE_ENUM_ROLE;
        boolean is_role = true;
        if (role_name.equals("辅导员")) {
            is_role = false;
        }

        List<String> rangeList = new ArrayList<>();
        if (!is_role) {
            List<SmsUser> list = commonUtil.findInstructorByClassID(stuClassOrgId);
            if (list != null) {
                for (SmsUser user:list){
                    rangeList.add(user.getId());
                    range_type = RangeTypeEnum.RANGE_TYPE_ENUM_PERSON;
                }
            }
        } else {
            rangeList.add(role_id);
        }

        newTipsUtil.addNewTips(TipsTypeEnum.TIPS_TYPE_ENUM_ALLOW,
                user_id,
                range_type,
                rangeList,
                AppTypeEnum.APP_TYPE_ENUM_LEAVE,
                smsLeave.getId(),
                process_detail_id);
        return CommonResult.success();
    }

    @Override
    @Transactional
    public ResponseResult applyLeaveCancel(SmsLeave smsLeave, String user_id) {
        if (isNullOrEmpty(smsLeave.getId())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        SmsLeave stuLeave = smsLeaveMapper.selectById(smsLeave.getId());
        if (stuLeave == null) {
            return CommonResult.failed(CommonCodeEnum.LEAVE_NOT_EXIST);
        }

        if (!stuLeave.getUserId().equals(user_id)) {
            return CommonResult.failed(CommonCodeEnum.PERMISSION_DENY);
        }

        if (stuLeave.getIsAllow() != ALLOW_FLAG_WAIT) {
            return CommonResult.failed(CommonCodeEnum.LEAVE_CAN_NOT_CANCEL);
        }

        SmsLeave cancelLeave = new SmsLeave();
        cancelLeave.setId(smsLeave.getId());
        cancelLeave.setIsAllow(ALLOW_FLAG_CANCEL);
        smsLeaveMapper.updateById(cancelLeave);

        QueryWrapper<SmsLeaveDetail> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(SmsLeaveDetail::getLeaveId, smsLeave.getId());
        List<SmsLeaveDetail> detailList = smsLeaveDetailMapper.selectList(queryWrapper);
        boolean is_allowing = false;
        if (detailList != null && detailList.size() > 0) {
            for (SmsLeaveDetail detail : detailList) {
                if (detail.getIsAllow().equals(ALLOW_FLAG_PASS) || detail.getIsAllow().equals(ALLOW_FLAG_DENY)) {
                    is_allowing = true;
                }
            }
        }
        if (is_allowing) {
            return CommonResult.failed(CommonCodeEnum.LEAVE_CAN_NOT_CANCEL_ALLOWING);
        }
        SmsLeaveDetail smsLeaveDetail = new SmsLeaveDetail();
        smsLeaveDetail.setIsAllow(ALLOW_FLAG_CANCEL);
        smsLeaveDetailMapper.update(smsLeaveDetail, queryWrapper);

        //消息通知 关闭
        newTipsUtil.cancelFinishTips(smsLeave.getId());

        return CommonResult.success();
    }

    @Override
    public ResponseResult getLeaveDetail(String leave_id) {
        if (isNullOrEmpty(leave_id)) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        SmsLeave smsLeave = smsLeaveMapper.selectById(leave_id);
        if (smsLeave == null) {
            return CommonResult.failed(CommonCodeEnum.LEAVE_NOT_EXIST);
        }
        QueryWrapper<SmsLeaveDetail> detailQueryWrapper = new QueryWrapper<>();
        detailQueryWrapper.lambda().eq(SmsLeaveDetail::getLeaveId, leave_id);
        List<SmsLeaveDetail> detailList = smsLeaveDetailMapper.selectList(detailQueryWrapper);
        List<SmsLeaveDetailResp> detailRespList = detailList.stream().map(detail -> {
            SmsLeaveDetailResp detailResp = new SmsLeaveDetailResp();
            BeanUtils.copyProperties(detail, detailResp);
            if (detail.getIsAllow().equals(ALLOW_FLAG_PASS) || detail.getIsAllow().equals(ALLOW_FLAG_DENY)) {
                SmsUser smsUser = smsUserMapper.selectById(detail.getAllowUser());
                SmsLeaveUserResp userResp = new SmsLeaveUserResp();
                BeanUtils.copyProperties(smsUser, userResp);
                detailResp.setSmsLeaveUserResp(userResp);
            }
            return detailResp;
        }).collect(Collectors.toList());

        LeaveDetailResp leaveResp = new LeaveDetailResp();
        BeanUtils.copyProperties(smsLeave, leaveResp);
        leaveResp.setDetailList(detailRespList);
        return CommonResult.success(leaveResp);
    }

    @Override
    public ResponseResult studentGetLeaveList(Integer pageSize, Integer pageNum, String user_id) {
        Page<SmsLeave> page = new Page<>(pageNum, pageSize);
        QueryWrapper<SmsLeave> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(SmsLeave::getUserId, user_id).eq(SmsLeave::getIsAllow, ALLOW_FLAG_WAIT)
                .orderByDesc(SmsLeave::getCreateTime);
        smsLeaveMapper.selectPage(page, queryWrapper);
        int total = (int) page.getTotal();
        List<SmsLeave> list = page.getRecords();
        List<SmsLeaveResp> leaveRespList = new ArrayList<>();
        if (list != null && list.size() > 0) {
            for (SmsLeave leave : list) {
                SmsLeaveResp smsLeaveResp = new SmsLeaveResp();
                BeanUtils.copyProperties(leave, smsLeaveResp);
                leaveRespList.add(smsLeaveResp);
            }
        }
        return CommonResult.success(leaveRespList, total);
    }

    @Override
    public ResponseResult studentHistoryGetLeaveList(Integer pageSize, Integer pageNum, Integer allow_flag, String user_id
            , Integer leaveType, String bgDate, String endDate) {
        Page<SmsLeave> page = new Page<>(pageNum, pageSize);
        QueryWrapper<SmsLeave> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().ne(SmsLeave::getIsAllow, ALLOW_FLAG_WAIT)
                .eq(SmsLeave::getUserId, user_id)
                .orderByDesc(SmsLeave::getCreateTime);
        if (allow_flag != null) {
            queryWrapper.lambda().eq(SmsLeave::getIsAllow, allow_flag);
        }
        if (leaveType != null) {
            queryWrapper.lambda().eq(SmsLeave::getLeaveType, leaveType);
        }
        if (bgDate != null && !bgDate.equals("")) {
            String bg_date = bgDate + " 00:00:00";
            if (TimeUtil.StringtoDate(bg_date) == null) {
                return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
            }
            queryWrapper.lambda().ge(SmsLeave::getCreateTime, bg_date);
        }
        if (endDate != null && !endDate.equals("")) {
            String end_date = endDate + " 23:59:59";
            if (TimeUtil.StringtoDate(end_date) == null) {
                return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
            }
            queryWrapper.lambda().le(SmsLeave::getCreateTime, end_date);
        }

        smsLeaveMapper.selectPage(page, queryWrapper);
        int total = (int) page.getTotal();
        List<SmsLeave> list = page.getRecords();
        List<SmsLeaveResp> leaveRespList = new ArrayList<>();
        if (list != null && list.size() > 0) {
            for (SmsLeave leave : list) {
                SmsLeaveResp smsLeaveResp = new SmsLeaveResp();
                BeanUtils.copyProperties(leave, smsLeaveResp);
                leaveRespList.add(smsLeaveResp);
            }
        }
        return CommonResult.success(leaveRespList, total);
    }

    @Override
    public ResponseResult leaveAllow(SmsLeaveAllowReq smsLeaveAllowReq, String user_id) {
        if (isNullOrEmpty(smsLeaveAllowReq.getDetail_id()) || isNullOrEmpty(smsLeaveAllowReq.getLeave_id())
                || isNullOrEmpty(smsLeaveAllowReq.getIs_allow())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        QueryWrapper<SmsLeaveDetail> detailQueryWrapper = new QueryWrapper<>();
        detailQueryWrapper.lambda().eq(SmsLeaveDetail::getIsAllow, ALLOW_FLAG_WAIT)
                .eq(SmsLeaveDetail::getId, smsLeaveAllowReq.getDetail_id());
        SmsLeaveDetail smsLeaveDetail = smsLeaveDetailMapper.selectOne(detailQueryWrapper);
        if (smsLeaveDetail == null) {
            return CommonResult.failed(CommonCodeEnum.LEAVE_ALLOWED);
        }

        //判断小于当前sort的detail中是否有未审批的
        QueryWrapper<SmsLeaveDetail> ltQueryWrapper = new QueryWrapper<>();
        ltQueryWrapper.lambda().eq(SmsLeaveDetail::getIsAllow, ALLOW_FLAG_WAIT)
                .eq(SmsLeaveDetail::getLeaveId, smsLeaveAllowReq.getLeave_id())
                .lt(SmsLeaveDetail::getAllowSort, smsLeaveDetail.getAllowSort());
        List<SmsLeaveDetail> ltDetailList = smsLeaveDetailMapper.selectList(ltQueryWrapper);
        if (ltDetailList != null && ltDetailList.size() > 0) {
            return CommonResult.failed(CommonCodeEnum.LEAVE_ALLOW_PRE_NOT_ALLOW);
        }

        QueryWrapper<SmsLeave> leaveQueryWrapper = new QueryWrapper<>();
        leaveQueryWrapper.lambda().eq(SmsLeave::getIsAllow, ALLOW_FLAG_WAIT)
                .eq(SmsLeave::getId, smsLeaveAllowReq.getLeave_id());
        SmsLeave smsLeave = smsLeaveMapper.selectOne(leaveQueryWrapper);
        if (smsLeave == null) {
            return CommonResult.failed(CommonCodeEnum.LEAVE_ALLOWED);
        }

        //判断当前审批人角色是否含有和detail相同
        QueryWrapper<SmsUserRoleRelation> userRoleQueryWrapper = new QueryWrapper<>();
        userRoleQueryWrapper.lambda().eq(SmsUserRoleRelation::getUserId, user_id);
        List<SmsUserRoleRelation> roleRelationList = smsUserRoleRelationMapper.selectList(userRoleQueryWrapper);
        List<String> roleIdList = roleRelationList.stream().map(SmsUserRoleRelation::getRoleId).collect(Collectors.toList());
        List<String> filterRoleList = roleIdList.stream().filter(roleId -> roleId.equals(smsLeaveDetail.getRoleId())).collect(Collectors.toList());
        if (filterRoleList.size() < 1) {
            return CommonResult.failed(CommonCodeEnum.PERMISSION_DENY);
        }

        boolean is_done = false;
        boolean is_allow = false;

        //判断当前detail是否是辅导员
        if (smsLeaveDetail.getRoleId().equals(ROLE_INSTRUCTOR_ID)) {
            QueryWrapper<SmsOrgUserRelation> orgUserRelationQueryWrapper = new QueryWrapper<>();
            orgUserRelationQueryWrapper.lambda().eq(SmsOrgUserRelation::getUserId, user_id);
            List<SmsOrgUserRelation> orgUserRelationList = smsOrgUserRelationMapper.selectList(orgUserRelationQueryWrapper);
            List<String> orgList = orgUserRelationList.stream().map(SmsOrgUserRelation::getOrgId).collect(Collectors.toList());

            QueryWrapper<SmsOrgStructure> orgStructureQueryWrapper = new QueryWrapper<>();
            orgStructureQueryWrapper.lambda().in(SmsOrgStructure::getId, orgList).eq(SmsOrgStructure::getLevel, ORG_TYPE_CLASS);
            SmsOrgStructure smsOrgStructure = smsOrgStructureMapper.selectOne(orgStructureQueryWrapper);
            if (smsOrgStructure == null) {
                return CommonResult.failed(CommonCodeEnum.LEAVE_ALLOW_NOT_OWN_CLASS);
            }
        }

        //审批并判断sort是否是最后一个流程
        SmsLeaveDetail allowDetail = new SmsLeaveDetail();
        allowDetail.setId(smsLeaveAllowReq.getDetail_id());
        allowDetail.setIsAllow(smsLeaveAllowReq.getIs_allow());
        allowDetail.setAllowUser(user_id);
        allowDetail.setAllowTime(new Date());
        smsLeaveDetailMapper.updateById(allowDetail);

        QueryWrapper<SmsLeaveDetail> QueryWrapper = new QueryWrapper<>();
        QueryWrapper.lambda().eq(SmsLeaveDetail::getLeaveId, smsLeaveAllowReq.getLeave_id());
        List<SmsLeaveDetail> list = smsLeaveDetailMapper.selectList(QueryWrapper);
        if (smsLeaveAllowReq.getIs_allow().equals(ALLOW_FLAG_DENY) || list.size() == smsLeaveDetail.getAllowSort()) {
            is_done = true;
            SmsLeave allowLeave = new SmsLeave();
            allowLeave.setId(smsLeaveAllowReq.getLeave_id());
            allowLeave.setIsAllow(smsLeaveAllowReq.getIs_allow());
            allowLeave.setAllowReason(smsLeaveAllowReq.getAllow_reason());
            allowLeave.setEndTime(new Date());
            smsLeaveMapper.updateById(allowLeave);
        }

        //发布消息通知待办
        SmsOrgStructure stuOrgClass = commonUtil.getUserOrgClass(smsLeave.getUserId());
        if (stuOrgClass != null){
            RangeTypeEnum range_type = RangeTypeEnum.RANGE_TYPE_ENUM_ROLE;

            if (is_done) {
                if (smsLeaveAllowReq.getIs_allow() == ALLOW_FLAG_PASS){
                    is_allow = true;
                }
                newTipsUtil.allowFinishTips(smsLeaveAllowReq.getLeave_id(),
                        user_id,
                        is_allow);
            } else {
                List<String> rangeList = new ArrayList<>();
                //判断下一流程是否辅导员
                String role_id = list.get(smsLeaveDetail.getAllowSort()).getRoleId();
                String roleName = smsRoleMapper.selectById(role_id).getRoleName();

                if (roleName.equals("辅导员")) {
                    List<SmsUser> list1 = commonUtil.findInstructorByClassID(stuOrgClass.getId());
                    if (list1 != null) {
                        for (SmsUser user:list1){
                            rangeList.add(user.getId());
                            range_type = RangeTypeEnum.RANGE_TYPE_ENUM_PERSON;
                        }
                    }
                } else {
                    rangeList.add(role_id);
                }

                newTipsUtil.allowContinueTips(smsLeaveAllowReq.getLeave_id(),
                        user_id,
                        range_type,
                        rangeList,
                        list.get(smsLeaveDetail.getAllowSort()).getId());
            }
        }
        return CommonResult.success();
    }


    @Override
    public ResponseResult teacherAllowGetLeaveList(Integer pageSize, Integer pageNum, String user_id, Integer leaveType, String applyName, String bgDate, String endDate) {
        List<LeaveDetailResp> list = new ArrayList<>();
        List<String> filterLeaveIDList = new ArrayList<>();

        //获取未完成申请id
        List<String> leaveNotFinishList = smsLeaveMapper.selectList(new QueryWrapper<SmsLeave>()
                .lambda()
                .eq(SmsLeave::getIsAllow, ALLOW_FLAG_WAIT))
                .stream()
                .map(SmsLeave::getId)
                .collect(Collectors.toList());

        //获取被拒绝申请id
        List<String> leaveDenyList = smsLeaveMapper.selectList(new QueryWrapper<SmsLeave>()
                .lambda()
                .eq(SmsLeave::getIsAllow, ALLOW_FLAG_DENY))
                .stream()
                .map(SmsLeave::getId)
                .collect(Collectors.toList());

        //获取查询用户所有角色
//        QueryWrapper<SmsUserRoleRelation> userRoleQueryWrapper = new QueryWrapper<>();
//        userRoleQueryWrapper.lambda().eq(SmsUserRoleRelation::getUserId, user_id);
//        List<SmsUserRoleRelation> roleRelationList = smsUserRoleRelationMapper.selectList(userRoleQueryWrapper);
//        List<String> roleIdList = roleRelationList.stream().map(SmsUserRoleRelation::getRoleId).collect(Collectors.toList());
        List<String> roleIdList = cacheUtil.getRoleList(user_id);

        QueryWrapper<SmsLeaveDetail> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("DISTINCT leave_id").lambda().in(SmsLeaveDetail::getRoleId, roleIdList)
                .eq(SmsLeaveDetail::getIsAllow, ALLOW_FLAG_WAIT);
        if (leaveNotFinishList.size() > 0) {
            queryWrapper.lambda().in(SmsLeaveDetail::getLeaveId, leaveNotFinishList);
        }
        if (leaveDenyList.size() > 0) {
            queryWrapper.lambda().notIn(SmsLeaveDetail::getLeaveId, leaveDenyList);
        }
        List<SmsLeaveDetail> detailList = smsLeaveDetailMapper.selectList(queryWrapper);
        List<String> leaveIdList = detailList.stream().map(SmsLeaveDetail::getLeaveId).collect(Collectors.toList());
        if (leaveIdList.size() < 1) {
            return CommonResult.success(list, 0);
        }

        filterLeaveIDList = leaveIdList.stream().filter(leave_id -> {
            SmsLeave smsLeave = smsLeaveMapper.selectById(leave_id);
            QueryWrapper<SmsLeaveDetail> detailQueryWrapper = new QueryWrapper<>();
            detailQueryWrapper.lambda().eq(SmsLeaveDetail::getLeaveId, leave_id);
            List<SmsLeaveDetail> filterDetailList = smsLeaveDetailMapper.selectList(detailQueryWrapper);
            boolean filter_flag = false;
            if (filterDetailList != null && filterDetailList.size() > 0) {
                for (SmsLeaveDetail detail : filterDetailList) {
                    if (detail.getIsAllow().equals(ALLOW_FLAG_DENY) || detail.getIsAllow().equals(ALLOW_FLAG_CANCEL)) {
                        return false;
                    }
                    List<String> roleList = roleIdList.stream().filter(role -> role.equals(detail.getRoleId())).collect(Collectors.toList());
                    if (roleList.size() > 0) {
                        //判断辅导员 辅导员必须和申请学生同班
                        if (detail.getRoleName().equals("辅导员")) {
                            boolean bl = teacherIsTrue(user_id, smsLeave.getUserId());
                            if (!bl) {
                                continue;
                            } else {
                                return true;
                            }
                        }

                        if (detail.getIsAllow() == ALLOW_FLAG_WAIT) {
                            return true;
                        }
//                        QueryWrapper<SmsLeaveDetail> ltQueryWrapper = new QueryWrapper<>();
//                        ltQueryWrapper.lambda().eq(SmsLeaveDetail::getIsAllow, ALLOW_FLAG_WAIT)
//                                .eq(SmsLeaveDetail::getLeaveId, leave_id)
//                                .gt(SmsLeaveDetail::getAllowSort, detail.getAllowSort());
//                        List<SmsLeaveDetail> ltDetailList = smsLeaveDetailMapper.selectList(ltQueryWrapper);
//                        if (ltDetailList != null && ltDetailList.size() > 0) {
//                            filter_flag = true;
//                        } else {
//                            return true;
//                        }
                    }
                }
            }
            return false;
        }).collect(Collectors.toList());


        if (filterLeaveIDList.size() < 1) {
            return CommonResult.success(list, 0);
        }
        Page<SmsLeave> page = new Page<>(pageNum, pageSize);
        QueryWrapper<SmsLeave> leaveQueryWrapper = new QueryWrapper<>();
        leaveQueryWrapper.lambda().in(SmsLeave::getId, filterLeaveIDList).orderByDesc(SmsLeave::getCreateTime);
        if (!isNullOrEmpty(leaveType)) {
            leaveQueryWrapper.lambda().eq(SmsLeave::getLeaveType, leaveType);
        }
        if (!isNullOrEmpty(applyName)) {
            leaveQueryWrapper.lambda().like(SmsLeave::getStuName, applyName);
        }
        if (!isNullOrEmpty(bgDate)) {
            String strDate = bgDate + " 00:00:00";
            if (TimeUtil.StringtoDate(strDate) != null) {
                leaveQueryWrapper.lambda().ge(SmsLeave::getCreateTime, strDate);
            }
        }
        if (!isNullOrEmpty(endDate)) {
            String strDate = endDate + " 23:59:59";
            if (TimeUtil.StringtoDate(strDate) != null) {
                leaveQueryWrapper.lambda().le(SmsLeave::getCreateTime, strDate);
            }
        }
        smsLeaveMapper.selectPage(page, leaveQueryWrapper);
        int total = (int) page.getTotal();
        list = page.getRecords().stream().map(smsLeave -> {
            LeaveDetailResp leaveDetailResp = new LeaveDetailResp();
            BeanUtils.copyProperties(smsLeave, leaveDetailResp);
            return leaveDetailResp;
        }).collect(Collectors.toList());
        return CommonResult.success(list, total);
    }

    private boolean teacherIsTrue(String teacher_id, String student_id) {
        QueryWrapper<SmsOrgUserRelation> orgUserRelationQueryWrapper = new QueryWrapper<>();
        orgUserRelationQueryWrapper.lambda().eq(SmsOrgUserRelation::getUserId, student_id);
        List<SmsOrgUserRelation> orgUserRelationList = smsOrgUserRelationMapper.selectList(orgUserRelationQueryWrapper);
        if (orgUserRelationList == null || orgUserRelationList.size() < 1) {
            return false;
        }
        List<String> orgIDList = orgUserRelationList.stream().map(SmsOrgUserRelation::getOrgId).collect(Collectors.toList());
        QueryWrapper<SmsOrgStructure> orgStructureQueryWrapper = new QueryWrapper<>();
        orgStructureQueryWrapper.lambda().in(SmsOrgStructure::getId, orgIDList).eq(SmsOrgStructure::getLevel, ORG_TYPE_CLASS);
        List<SmsOrgStructure> orgStructureList = smsOrgStructureMapper.selectList(orgStructureQueryWrapper);
        if (orgStructureList == null || orgStructureList.size() < 1) {
            return false;
        }
        Integer stuClassOrgId = orgStructureList.get(0).getId();


        QueryWrapper<SmsOrgUserRelation> teacherQueryWrapper = new QueryWrapper<>();
        orgUserRelationQueryWrapper.lambda().eq(SmsOrgUserRelation::getUserId, teacher_id);
        List<SmsOrgUserRelation> orgTeacherRelationList = smsOrgUserRelationMapper.selectList(teacherQueryWrapper);
        if (orgTeacherRelationList == null || orgTeacherRelationList.size() < 1) {
            return false;
        }
        List<String> teacherOrgIDList = orgTeacherRelationList.stream().map(SmsOrgUserRelation::getOrgId).collect(Collectors.toList());
        List<String> filterTeacherOrgIDList = teacherOrgIDList.stream()
                .filter(teacherOrgID -> teacherOrgID.equals(stuClassOrgId.toString()))
                .collect(Collectors.toList());
        if (filterTeacherOrgIDList.size() < 1) {
            return false;
        }
        return true;
    }


    @Override
    public ResponseResult teacherHistoryGetLeaveList(Integer pageSize, Integer pageNum, Integer allow_flag, String user_id, Integer leaveType, String applyName, String bgDate, String endDate) {
        List<SmsLeaveResp> list = new ArrayList<>();

        QueryWrapper<SmsLeaveDetail> detailQueryWrapper = new QueryWrapper<>();
        detailQueryWrapper.select("DISTINCT leave_id").lambda().eq(SmsLeaveDetail::getAllowUser, user_id)
                .ne(SmsLeaveDetail::getIsAllow, ALLOW_FLAG_WAIT);
        if (allow_flag != null) {
            detailQueryWrapper.lambda().eq(SmsLeaveDetail::getIsAllow, allow_flag);
        }
        if (!isNullOrEmpty(bgDate)) {
            String strDate = bgDate + " 00:00:00";
            if (TimeUtil.StringtoDate(strDate) != null) {
                detailQueryWrapper.lambda().ge(SmsLeaveDetail::getAllowTime, strDate);
            }
        }
        if (!isNullOrEmpty(endDate)) {
            String strDate = endDate + " 23:59:59";
            if (TimeUtil.StringtoDate(strDate) != null) {
                detailQueryWrapper.lambda().le(SmsLeaveDetail::getAllowTime, strDate);
            }
        }
        List<SmsLeaveDetail> detailList = smsLeaveDetailMapper.selectList(detailQueryWrapper);
        List<String> leaveIdList = detailList.stream().map(SmsLeaveDetail::getLeaveId).collect(Collectors.toList());

        int total = 0;
        if (leaveIdList.size() > 0) {
            QueryWrapper<SmsLeave> mpjLambdaWrapper = new QueryWrapper<>();
            mpjLambdaWrapper.lambda().in(SmsLeave::getId, leaveIdList);
            if (!isNullOrEmpty(leaveType)) {
                mpjLambdaWrapper.lambda().eq(SmsLeave::getLeaveType, leaveType);
            }
            if (!isNullOrEmpty(applyName)) {
                mpjLambdaWrapper.lambda().like(SmsLeave::getStuName, applyName);
            }
            mpjLambdaWrapper.lambda()
//                .orderByDesc(SmsLeave::getEndTime)
                    .orderByDesc(SmsLeave::getCreateTime);
            Page<SmsLeave> page = new Page<>(pageNum, pageSize);
            smsLeaveMapper.selectPage(page,
                    mpjLambdaWrapper
            );

            total = (int) page.getTotal();
            list = page.getRecords().stream().map(smsLeave -> {
                SmsLeaveResp leaveDetailResp = new SmsLeaveResp();
                BeanUtils.copyProperties(smsLeave, leaveDetailResp);
                return leaveDetailResp;
            }).collect(Collectors.toList());
        }
        return CommonResult.success(list, total);
    }

    @Override
    public ResponseResult leaveConfirm(SmsLeaveConfirmResp smsLeaveConfirmResp, String user_id) {
        if (isNullOrEmpty(smsLeaveConfirmResp.getLeave_id()) || isNullOrEmpty(smsLeaveConfirmResp.getConfirm_type())
                || isNullOrEmpty(smsLeaveConfirmResp.getQr_id())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        SmsQr smsQr = smsQrMapper.selectOne(new QueryWrapper<SmsQr>()
                .lambda()
                .eq(SmsQr::getId, smsLeaveConfirmResp.getQr_id())
                .eq(SmsQr::getQrType, QR_TYPE_LEAVE));
        if (smsQr == null || smsQr.getId() == null) {
            return CommonResult.failed(CommonCodeEnum.QR_NOT_EXIST);
        }
        String qr_position = smsQr.getQrPosition();

        List<SmsLeave> leaveList = smsLeaveMapper.selectList(new QueryWrapper<SmsLeave>()
                .lambda()
                .eq(SmsLeave::getId, smsLeaveConfirmResp.getLeave_id())
                .eq(SmsLeave::getUserId, user_id));
        if (leaveList == null || leaveList.size() < 1) {
            return CommonResult.failed(CommonCodeEnum.LEAVE_OWN_NOT_EXIST);
        }

        SmsLeave smsLeave = leaveList.get(0);

        if (smsLeave.getIsAllow() != ALLOW_FLAG_PASS) {
            return CommonResult.failed(CommonCodeEnum.LEAVE_NOT_FINISH);
        }

        if (smsLeaveConfirmResp.getConfirm_type() == CONFIRM_LEAVE) {
            if (smsLeave.getLeaveConfirm() == CONFIRM_STATUS_ON) {
                return CommonResult.failed(CommonCodeEnum.LEAVE_LEAVE_CONFIRM_ALREADY);
            }
            SmsLeave confirmLeave = new SmsLeave();
            confirmLeave.setLeaveConfirmTime(new Date());
            confirmLeave.setLeaveConfirm(CONFIRM_STATUS_ON);
            confirmLeave.setLeaveConfirmPosition(qr_position);
            confirmLeave.setId(smsLeaveConfirmResp.getLeave_id());
            smsLeaveMapper.updateById(confirmLeave);
        } else if (smsLeaveConfirmResp.getConfirm_type() == CONFIRM_COME) {
            if (smsLeave.getComeConfirm() == CONFIRM_STATUS_ON) {
                return CommonResult.failed(CommonCodeEnum.LEAVE_COME_CONFIRM_ALREADY);
            }
            SmsLeave confirmLeave = new SmsLeave();
            confirmLeave.setComeConfirmTime(new Date());
            confirmLeave.setComeConfirm(CONFIRM_STATUS_ON);
            confirmLeave.setComeConfirmPosition(qr_position);
            confirmLeave.setId(smsLeaveConfirmResp.getLeave_id());
            smsLeaveMapper.updateById(confirmLeave);
        }
        return CommonResult.success();
    }
}
